#include<iostream>
#include<vector>
#include<string>
#include<queue>
#include<pthread.h>
#include<stdbool.h>
struct threadinfo
{
    std::string _name;
    pthread_t tid;
};
template<class T>
class threadpool
{
    const static int defualtsize=5;
private:
    void Lock()
    {
        pthread_mutex_lock(&_mutex);
    }
    void UnLock()
    {
        pthread_mutex_unlock(&_mutex);
    }
    void WakeUp()
    {
        pthread_cond_signal(&_cond);
    }
    void ThreadSleep()
    {
        pthread_cond_wait(&_cond,&_mutex);
    }
    bool IsQueueEmpty()
    {
        _tasks.empty();
    }
    std::string GetName(pthread_t tid)
    {
        for(auto& e: _threadinfo)
        {
            if(e.tid==tid)
                return e._name;
        }
        return "nullptr";
    }
    static void* Handle(void* args)
    {
        threadpool<T>* tp=static_cast<threadpool<T>*>(args);
        while(true)
        {
            tp->Lock();
            while(tp->IsQueueEmpty())
            {
                tp->ThreadSleep();
            }
            T t=tp->Pop();
            tp->UnLock();
            t();
            std::cout<<tp->GetName(pthread_self())<<" "<<"result"<<" "<<t.GetResult()<<std::endl;
        }
    }
public:
    threadpool(int cap=defualtsize)
        :_threadinfo(cap),_capecity(cap)
    {
        pthread_mutex_init(&_mutex,nullptr);
        pthread_cond_init(&_cond,nullptr);
    }
    void Start()
    {
        for(int i=0;i<_threadinfo.size();i++)
        {
            _threadinfo[i]._name="thread "+std::to_string(+i+1);
            pthread_create(&_threadinfo[i].tid,nullptr,Handle,this);
            std::cout<<"create"<<" "<<_threadinfo[i]._name<<" "<<std::endl;
        }
    }
    void Push(const T& in)
    {
        Lock();
        _tasks.push(in);
        WakeUp();
        UnLock();
    }
    T Pop()
    {
        T out=_tasks.front();
        _tasks.pop();
        return out;
    }
    ~threadpool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }
private:
    int _capecity;
    std::vector<threadinfo> _threadinfo;
    std::queue<T> _tasks;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;
};